package com.cennavi.mineplay.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.JdbcTemplate;

public class HeatmapUtils {

	public static class Grid {
		private double min_lng;

		private double max_lng;
		private double min_lat;
		private double max_lat;

		public double getMin_lng() {
			return min_lng;
		}

		public double getMax_lng() {
			return max_lng;
		}

		public double getMin_lat() {
			return min_lat;
		}

		public double getMax_lat() {
			return max_lat;
		}

		private double scale = 0.8;

		private int count;

		public Grid(double min_lng, double max_lng, double min_lat,
				double max_lat) {
			this.min_lng = min_lng;
			this.max_lng = max_lng;
			this.min_lat = min_lat;
			this.max_lat = max_lat;
		}

		public int getCount() {
			return count;
		}

		public void setCount(int count) {
			this.count += count;
		}

		public String getGridWKT() {

			double value = (1 - scale) / 2 * (this.max_lng - this.min_lng);

			double new_min_lng = min_lng + value;
			double new_max_lng = max_lng - value;

			double new_min_lat = min_lat + value;
			double new_max_lat = max_lat - value;
//			
//			double new_min_lng = min_lng;
//			double new_max_lng = max_lng;
//
//			double new_min_lat = min_lat;
//			double new_max_lat = max_lat;

			String wkt = "Polygon((" + new_min_lng + " " + new_min_lat + ","
					+ new_max_lng + " " + new_min_lat + "," + new_max_lng + " "
					+ new_max_lat + "," + new_min_lng + " " + new_max_lat + ","
					+ new_min_lng + " " + new_min_lat + "))";

			return wkt;
		}

		public String getHexgridWKT() {
			
			double value = (1 - scale) / 2 * (this.max_lng - this.min_lng);

			double new_min_lng = min_lng + value;
			double new_max_lng = max_lng - value;

			double new_min_lat = min_lat + value;
			double new_max_lat = max_lat - value;
			
			
			double p1_lng = new_min_lng;
			double p1_lat = (new_max_lat + new_min_lat) / 2;
			
			double p2_lng = new_min_lng + ((new_max_lng - new_min_lng) / 2 / Math.sqrt(3));
			double p2_lat = new_max_lat;
			
			double p3_lng = new_max_lng - ((new_max_lng - new_min_lng) / 2 / Math.sqrt(3));
			double p3_lat = new_max_lat;
			
			double p4_lng = new_max_lng;
			double p4_lat = (new_max_lat + new_min_lat) / 2;
			
			double p5_lng = new_max_lng - ((new_max_lng - new_min_lng) / 2 / Math.sqrt(3));
			double p5_lat = new_min_lat;
			
			double p6_lng = new_min_lng + ((new_max_lng - new_min_lng) / 2 / Math.sqrt(3));
			double p6_lat = new_min_lat;
			
			String wkt = "Polygon(("+
			p1_lng+" "+p1_lat+","+
			p2_lng+" "+p2_lat+","+
			p3_lng+" "+p3_lat+","+
			p4_lng+" "+p4_lat+","+
			p5_lng+" "+p5_lat+","+
			p6_lng+" "+p6_lat+","+
			p1_lng+" "+p1_lat+"))";

			return wkt;
		}

	}

	public static class Grids {

		private double min_lng;
 
		private double min_lat;
		 
		public double getMin_lng() {
			return min_lng;
		}

		public void setMin_lng(double min_lng) {
			this.min_lng = min_lng;
		}


		public double getMin_lat() {
			return min_lat;
		}

		public void setMin_lat(double min_lat) {
			this.min_lat = min_lat;
		}

		private double unit;

		public Grids(double min_lng,   double min_lat ,double unit) {
			this.min_lng = min_lng;
			this.min_lat = min_lat;
			this.unit = unit;
		}

		private List<List<Grid>> list = new ArrayList<>();

		public Grid getGrid(double lng, double lat) {
			
			int lng_idx = (int)Math.floor((lng - min_lng)/unit);
			int lat_idx = (int)Math.floor((lat - min_lat)/unit);
			
			Grid grid = list.get(lng_idx).get(lat_idx);
			
			return grid;
		}

		public List<List<Grid>> getList() {
			return list;
		}

		public void setList(List<List<Grid>> list) {
			this.list = list;
		}
		
		

	}

	public static double[] getGeomRange(String table_name, JdbcTemplate jdbc) {

		double[] range = new double[4];

		String sql = "select min(lng) as min_lng,max(lng) as max_lng,min(lat) as min_lat,max(lat) as max_lat from ( select cast(substr(txt,1,pos) as float) as lng,cast(substr(txt,pos+1) as float) as lat from ( select txt,strpos(txt,' ') as pos from ( select replace(replace(txt,'POINT(',''),')','') as txt from  (select  st_astext(geom) as txt from tablename) as foo1 ) as foo2 ) as foo3 ) as foo4";

		sql = sql.replace("tablename", table_name);

		Map<String, Object> map = jdbc.queryForMap(sql);

		range[0] = (double) map.get("min_lng");
		range[1] = (double) map.get("max_lng");
		range[2] = (double) map.get("min_lat");
		range[3] = (double) map.get("max_lat");

		return range;

	}

	public static Grids getGrids(double[] range, double min_lng,
			double max_lng, double min_lat, double max_lat, int splitNum) {

		double range_lng = range[1] - range[0];

		double unit = range_lng / splitNum;

		double start_lng = Math.floor((min_lng - range[0]) / unit) * unit
				+ range[0];
		double start_lat = Math.floor((min_lat - range[2]) / unit) * unit
				+ range[2];
		
		Grids grids = new Grids(start_lng,start_lat,unit);

		List<List<Grid>> totalGrid = new ArrayList<>();
		
		grids.setList(totalGrid);

		for (double lng = start_lng; lng <= max_lng; lng += unit) {

			List<Grid> rowsGrid = new ArrayList<>();

			for (double lat = start_lat; lat <= max_lat; lat += unit) {

				Grid grid = new Grid(lng, lng + unit, lat,
						lat + unit);

				rowsGrid.add(grid);
			}

			totalGrid.add(rowsGrid);
		}
		
		

		return grids;
	}

}
